import { ref, ComputedRef, unref, computed, onMounted, watchEffect, watch, toRaw } from 'vue';
import type { BasicTableProps } from '../types/table';
import type { PaginationProps } from '../types/pagination';
import { isBoolean, isFunction, isArray, isObject } from '@/utils/is';
import { APISETTING } from '../const';

import { cloneDeep } from 'lodash-es';

import { useMixins } from '@/hooks/useMixins';

import { v4 as uuidv4 } from 'uuid';

import { useDialog } from 'naive-ui';
import { dateFn } from '@render/utils/http/axios/ipcIndex';

export function useDataSource(
  propsRef: ComputedRef<BasicTableProps>,
  { getPaginationInfo, setPagination, setLoading, tableData, clearSorter, clearcheckedRowKeysFn },
  emit
) {
  const dialog = useDialog();

  const { routerType = 'add', t, message, handleTablePageFn } = useMixins();

  const dataSourceRef = ref<Recordable[]>([]);

  const editDataSourceRef: any = ref([]);

  const defaultRowObj: any = ref(null);

  const sorterOption: any = ref(null);

  watchEffect(() => {
    tableData.value = unref(dataSourceRef);
  });

  watch(
    () => unref(propsRef).dataSource,
    () => {
      const { dataSource }: any = unref(propsRef);
      dataSource && (dataSourceRef.value = dataSource);
    },
    {
      immediate: true,
    }
  );

  const getRowKey = computed(() => {
    const { rowKey, isEditTable = false }: any = unref(propsRef);
    return rowKey
      ? rowKey
      : ({ uuid }) => {
          return isEditTable ? uuid : 'key';
        };
  });

  const sortFn: any = (data = [], key = '') => {
    data.sort((aItem: any, bItem: any) => {
      if (typeof aItem[key] === 'number' && typeof bItem[key] === 'number') {
        return aItem[key] - bItem[key];
      } else if (typeof aItem[key] === 'string' && typeof bItem[key] === 'string') {
        return aItem[key].localeCompare(bItem[key]);
      }

      return 0;
    });

    return data;
  };

  const getDataSourceRef = computed(() => {
    const dataSource = unref(dataSourceRef);

    const sorterOptionObj = toRaw(sorterOption.value);

    if (!dataSource || dataSource.length === 0) {
      return unref(dataSourceRef);
    }

    if (sorterOptionObj) {
      const { columnKey = null, order = null } = sorterOptionObj;

      if (columnKey && order) {
        const data = cloneDeep(toRaw(dataSourceRef.value));

        let newData: any = [];

        if (order === 'descend') {
          newData = sortFn(data, columnKey);
        }

        if (order === 'ascend') {
          newData = sortFn(data, columnKey).reverse();
        }

        const { page = 1, pageSize = 10 } = unref(getPaginationInfo) as PaginationProps;

        // const { pageNum = 1, pageSize = 10 } = params;

        newData.forEach((item, key) => {
          item.index = (page - 1) * pageSize + key + 1;
        });

        return unref(newData);
      }
    }

    return unref(dataSourceRef);
  });

  // console.log(getDataSourceRef);

  async function fetch(opt?) {
    try {
      setLoading(true);
      const { request, pagination, beforeRequest, afterRequest }: any = unref(propsRef);

      if (!request) return;
      //组装分页信息
      const pageField = APISETTING.pageField;
      const sizeField = APISETTING.sizeField;
      const totalField = APISETTING.totalField;
      const listField = APISETTING.listField;

      let pageParams = {};
      const { page = 1, pageSize = 10 } = unref(getPaginationInfo) as PaginationProps;

      if ((isBoolean(pagination) && !pagination) || isBoolean(getPaginationInfo)) {
        pageParams = {};
      } else {
        pageParams[pageField] = (opt && opt[pageField]) || page;
        pageParams[sizeField] = pageSize;
      }

      let params: any = {
        ...pageParams,
      };
      if (beforeRequest && isFunction(beforeRequest)) {
        // The params parameter can be modified by outsiders
        params = (await beforeRequest(params)) || params;
      }

      let res = await request(params);

      // console.log(res)

      let resultInfo =
        res && res['data'] ? (res['data'][listField] ? res['data'][listField] : []) : [];

      if (res && res.data && res.data.records) {
        //临时处理报表类接口列表返回records

        resultInfo = res.data;

        const { records = [], total = 0 } = resultInfo;

        resultInfo = records || [];

        res = {
          code: 0,
          row: [...(records ? records : [])],
          total,
        };
      }

      if (!isArray(resultInfo)) {
        if (isObject(resultInfo)) {
          const { records = [], total = 0 } = resultInfo;

          resultInfo = records || [];

          res = {
            code: 200,
            row: [...(records ? records : [])],
            total,
          };
        } else {
          resultInfo = [];

          res = {
            code: 200,
            row: [],
            total: 0,
          };
        }
      }

      const resultTotal = res ? res?.data?.pagination[totalField] : 0 || 0;
      const currentPage = params[pageField];

      // 如果数据异常，需获取正确的页码再次执行

      // if (resultTotal) {
      //   if (page > resultTotal) {
      //     setPagination({
      //       [pageField]: resultTotal,
      //     });
      //     fetch(opt);
      //   }
      // }

      // console.log(resultInfo)

      if (resultInfo.length) {
        const { pageNum = 1, pageSize = 10 } = params;

        const num = (pageNum - 1) * pageSize;

        const isComputed = resultTotal > num;

        resultInfo.forEach((item, key) => {
          item.index = isComputed ? (pageNum - 1) * pageSize + key + 1 : key + 1;
          if (item.createTime) {
            item.createTime = dateFn(new Date(item.createTime));
          }

          if (item.updateTime) {
            item.updateTime = dateFn(new Date(item.updateTime));
          }
        });
      }

      if (afterRequest && isFunction(afterRequest)) {
        // can modify the data returned by the interface for processing
        resultInfo = await afterRequest(resultInfo);

        if (!isArray(resultInfo)) {
          resultInfo = [];
        }
      }

      clearSorter();

      sorterOption.value = null;

      dataSourceRef.value = resultInfo;
      setPagination({
        [pageField]: currentPage,
        [totalField]: resultTotal,
      });

      if (opt && opt[pageField]) {
        setPagination({
          [pageField]: opt[pageField] || 1,
        });
      }
      emit('fetch-success', {
        items: unref(resultInfo),
        resultTotal,
      });
    } catch (error) {
      console.error(error);
      emit('fetch-error', error);
      dataSourceRef.value = [];
      // setPagination({
      //   pageCount: 0,
      // });
    } finally {
      setLoading(false);
    }
  }

  function editTableHandleAddFn(fn = null) {
    const { pageSize = 10 } = unref(getPaginationInfo);

    editDataSourceRef.value.push(
      cloneDeep({
        ...defaultRowObj.value,
        uuid: uuidv4(),
        index: editDataSourceRef.value.length + 1,
      })
    );

    const total = editDataSourceRef.value.length;

    setPagination({
      page: Math.ceil(total / pageSize),
      total: editDataSourceRef.value.length,
    });

    getCurentPageDataFn();

    fn && fn(getEditTableDataFn());
  }

  function handleSetIndex(arr: any = []) {
    if (arr && arr.length) {
      arr.forEach((item, i) => {
        item.index = i + 1;
      });
    }
  }

  function getCurentPageDataFn() {
    const { pagination } = unref(propsRef) as any;

    if (pagination !== false) {
      const { page = 1, pageSize = 10, total = 0 } = unref(getPaginationInfo);

      const list = handleTablePageFn(editDataSourceRef.value, { pageNum: page, pageSize });

      if (!list.length && page !== 1 && page * pageSize > total) {
        setPagination({ page: page - 1 });

        getCurentPageDataFn();
        return;
      }

      dataSourceRef.value = list;
    } else {
      dataSourceRef.value = editDataSourceRef.value;
    }
  }

  function editTableHandleDeleteFn(delUuidList: any = [], fn = null) {
    dialog.warning({
      class: 'dialogBtn',
      title: t('common.tipMsg.info'),
      content: t('common.tipMsg.deleteSelectedMsg'),
      positiveText: t('common.button.primary'),
      negativeText: t('common.button.cancel'),
      positiveButtonProps: {
        color: '#307AFA',
        // type: 'info',
      },

      onPositiveClick: () => {
        const { page = 1, pageSize = 10 } = unref(getPaginationInfo);

        editDataSourceRef.value = editDataSourceRef.value.filter(
          (item) => !delUuidList.includes(item.uuid)
        );

        handleSetIndex(editDataSourceRef.value);

        const total = editDataSourceRef.value.length;

        const data = { total };

        if (total % pageSize === 0 && page != 1) {
          data['page'] = page - 1;
        }

        setPagination(data);

        getCurentPageDataFn();

        clearcheckedRowKeysFn(delUuidList);

        message.success(t('common.tipMsg.delSuccess'));

        fn && fn(getEditTableDataFn());
      },
      onNegativeClick: () => {
        // message.error('不确定');
      },
    });
  }

  onMounted(() => {
    const { noDefaultLoad, isEditTable = false, columns = [], defaultObj = null } = unref(propsRef);

    if (isEditTable) {
      if (defaultObj) {
        defaultRowObj.value = defaultObj;
      } else {
        const obj = {};

        for (const item of columns) {
          const { key = '' } = item;

          obj[key] = null;
        }

        defaultRowObj.value = obj;
      }

      if (routerType === 'add') {
        editTableHandleAddFn();
      }
    } else {
      !noDefaultLoad &&
        setTimeout(() => {
          fetch();
        }, 16);
    }
  });

  function setTableData(values) {
    // console.log(values);
    dataSourceRef.value = values;
  }

  function setSorterOption(option) {
    sorterOption.value = option;
  }

  function getDataSource(onlyGet?): any[] {
    const { page = 1, pageSize = 10 } = unref(getPaginationInfo) as PaginationProps;

    const arr: any[] = getDataSourceRef.value;
    if (onlyGet) return arr;
    arr.forEach((item: any, key: number) => {
      item.index = (page - 1) * pageSize + key + 1;
    });

    return arr;
  }

  async function reload(opt?) {
    await fetch(opt);
  }

  function setEditTableDataFn(obj) {
    const { record = {}, key = '', value, index = 1, data = {} } = obj;

    const { uuid = '' } = record;

    dataSourceRef.value[index][key] = value === undefined || value === 0 ? 0 : value || null;

    for (const i in data) {
      dataSourceRef.value[index][i] = data[i];
    }

    editDataSourceRef.value.every((item) => {
      if (item.uuid === uuid) {
        item[key] = value;

        for (const i in data) {
          item[i] = data[i];
        }

        return false;
      }

      return true;
    });
  }

  function setEditTableAllDataFn(list: any = []) {
    if (list && list.length) {
      const newList: any = [];

      list.forEach((item, key) => {
        newList.push({
          ...item,
          uuid: uuidv4(),
          index: key + 1,
        });
      });

      editDataSourceRef.value = newList;

      setPagination({
        total: newList.length,
      });

      getCurentPageDataFn();
    }
  }

  function getEditTableDataFn() {
    return toRaw(editDataSourceRef.value);
  }

  return {
    fetch,
    getRowKey,
    getDataSourceRef,
    getDataSource,
    setTableData,
    reload,
    setSorterOption,
    editTableHandleDeleteFn,
    editTableHandleAddFn,
    getCurentPageDataFn,
    setEditTableDataFn,
    getEditTableDataFn,
    setEditTableAllDataFn,
  };
}
